package tools

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/qichengzx/coordtransform"
	"io"
	"math"
	"net/http"
	"net/url"
	"regexp"
	"strconv"
	"strings"
)

// LngLat2Float 经纬度字符窜转成 float64
func LngLat2Float(str string) [2]float64 {
	arr := strings.Split(str, ",")
	if len(arr) == 2 {
		lng, _ := strconv.ParseFloat(strings.TrimSpace(arr[0]), 64)
		lat, _ := strconv.ParseFloat(strings.TrimSpace(arr[1]), 64)
		return [2]float64{lng, lat}
	}
	return [2]float64{0, 0}
}

// Haversine 计算两个经纬度的距离差, 误差10米
func Haversine(lat1, lon1, lat2, lon2 float64) float64 {
	// 转换为弧度
	lat1Rad := lat1 * (math.Pi / 180)
	lon1Rad := lon1 * (math.Pi / 180)
	lat2Rad := lat2 * (math.Pi / 180)
	lon2Rad := lon2 * (math.Pi / 180)

	// 度数差值
	latDiff := lat2Rad - lat1Rad
	lonDiff := lon2Rad - lon1Rad

	// 应用 Haversine 公式计算距离
	a := math.Pow(math.Sin(latDiff/2), 2) +
		math.Cos(lat1Rad)*math.Cos(lat2Rad)*math.Pow(math.Sin(lonDiff/2), 2)
	c := 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a))
	r := 6371.0 // 地球半径（单位：千米）

	distance := r * c
	return distance
}

type IpLocation struct {
	Status    string `json:"status"`
	Info      string `json:"info"`
	InfoCode  string `json:"infocode"`
	Province  string `json:"province"`
	City      string `json:"city"`
	AdCode    string `json:"adcode"`
	Rectangle string `json:"rectangle"`
}

// GetLocationByIP 高德地图通过ip获取地址信息, warning key已过期
func GetLocationByIP(ip string) (location *IpLocation, err error) {
	key := "3a69bef99855dc5d7e80809e59111a4b"
	params := url.Values{}
	params.Set("key", key)
	params.Set("ip", ip)
	reqUrl := "https://restapi.amap.com/v3/ip?" + params.Encode()
	fmt.Println("高德地图:  ", reqUrl)
	response, err := http.Get(reqUrl) //发起get请求
	if err != nil {
		return
	}
	defer response.Body.Close()            //关闭请求
	body, err := io.ReadAll(response.Body) //解析请求信息
	if err != nil {
		return
	}
	location = &IpLocation{}
	err = json.Unmarshal(body, location) //转换为map
	if err != nil {
		return
	}
	if location.Status == "0" {
		err = errors.New(location.Info)
		return
	}
	return
}

// BD09toGCJ02 百度转腾讯
func BD09toGCJ02(str string) string {
	arr := LngLat2Float(str)
	lng, lat := coordtransform.BD09toGCJ02(arr[0], arr[1])
	return fmt.Sprintf("%.8f,%.8f", lng, lat)
}

// BD09toWGS84 百度转WGS84 (cgcs2000)
func BD09toWGS84(str string) string {
	arr := LngLat2Float(str)
	lng, lat := coordtransform.BD09toWGS84(arr[0], arr[1])
	return fmt.Sprintf("%.8f,%.8f", lng, lat)
}

func GetLngLatGPSString(str string) [2]string {
	re := regexp.MustCompile(`^(\d{1,5}(\.\d{0,7})?)N,(\d{1,5}(\.\d{0,7})?)E$`)
	match := re.FindStringSubmatch(str)
	//fmt.Println("match", match)
	if len(match) == 5 {
		lat := LngLatFormat(match[1], 2)
		lng := LngLatFormat(match[3], 3)
		if lat != 0 && lng != 0 {
			//lng, lat = coordtransform.WGS84toGCJ02(lng, lat)
			return [2]string{strconv.FormatFloat(lng, 'f', 6, 64), strconv.FormatFloat(lat, 'f', 6, 64)}
		}
	}
	return [2]string{"", ""}
}

/*
GetLngLatGPSFloat
WGS-84:  GPS坐标系，国际标准，GPS模块使用。
GCJ-02:  火星坐标系，国测局坐标系，谷歌、高德、腾讯等使用。
BD-09:   百度坐标系，百度地图使用。
*/
func GetLngLatGPSFloat(str string) [2]float64 {
	re := regexp.MustCompile(`^(\d{1,5}(\.\d{0,7})?)N,(\d{1,5}(\.\d{0,7})?)E$`)
	match := re.FindStringSubmatch(str)
	//fmt.Println("match", match)
	if len(match) == 5 {
		lat := LngLatFormat(match[1], 2)
		lng := LngLatFormat(match[3], 3)
		//lng, lat = coordtransform.WGS84toGCJ02(lng, lat)
		return [2]float64{lng, lat}
	}
	return [2]float64{0, 0}
}

// LngLatFormat midIndex 2 lat 3 lng
func LngLatFormat(str string, midIndex int) float64 {
	re := regexp.MustCompile(`^(\d{1,7}(\.\d{0,7})?)$`)
	match := re.FindStringSubmatch(str)
	if len(match) == 3 {
		f1, err := strconv.ParseFloat(SubStr(str, 0, midIndex), 64)
		if err != nil {
			return 0
		}
		f2, err := strconv.ParseFloat(SubStr(str, midIndex, 15), 64)
		if err != nil {
			return 0
		}
		return f1 + f2/60
	} else {
		return 0
	}
}
